// Copyright 2007, 2008, 2009, 2010, 2011 The Apache Software Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.hxzon.tapestry5.components;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentParameterConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.Link;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.annotations.Environmental;
import org.apache.tapestry5.annotations.Events;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.services.ClientBehaviorSupport;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.hxzon.tapestry5.util.TapestryEx;

/**
 * Generates a series of links used to jump to a particular page index within the overall data set.
 * 
 * @tapestrydoc
 */
@Events(TapestryEx.Event_GridInplaceUpdate + " (internal event)")
public class GridExPager {

    /**
     * The current page number (indexed from 1).
     */
    @Parameter(value = "1", required = true)
    private long currentPage;

    @Parameter(value = "1", required = true)
    private long maxPage;
    /**
     * Number of pages before and after the current page in the range. The pager always displays links for 2 * range + 1
     * pages, unless that's more than the total number of available pages.
     */
    @Parameter(value = BindingConstants.SYMBOL + ":" + ComponentParameterConstants.GRIDPAGER_PAGE_RANGE)
    private int range;

    /**
     * If not null, then each link is output as a link to update the specified zone.
     */
    @Parameter
    private String zone;

    private long lastIndex;

    @Inject
    private ComponentResources resources;

    @Inject
    private Messages messages;

    @Environmental
    private ClientBehaviorSupport clientBehaviorSupport;

    @Environmental
    private JavaScriptSupport jsSupport;

    void beginRender(MarkupWriter writer) {
        if (maxPage < 2) {
            return;
        }

        writer.element("div", "class", "t-data-grid-pager");

        lastIndex = 0;

        for (int i = 1; i <= 2; i++) {
            writePageLink(writer, i);
        }

        long low = currentPage - range;
        long high = currentPage + range;

        if (low < 1) {
            low = 1;
            high = 2 * range + 1;
        } else {
            if (high > maxPage) {
                high = maxPage;
                low = high - 2 * range;
            }
        }

        for (long i = low; i <= high; i++) {
            writePageLink(writer, i);
        }

        for (long i = maxPage - 1; i <= maxPage; i++) {
            writePageLink(writer, i);
        }

        writer.end();
    }

    private void writePageLink(MarkupWriter writer, long pageIndex) {
        if (pageIndex < 1 || pageIndex > maxPage) {
            return;
        }
        if (pageIndex <= lastIndex) {
            return;
        }
        if (pageIndex != lastIndex + 1) {
            writer.write(" ... ");
        }
        lastIndex = pageIndex;

        boolean zoneIsNull = (zone == null);
        Object[] context = zoneIsNull ? new Object[] { pageIndex } : new Object[] { pageIndex, zone };
        //change by hxzon,use containerResources
        Link link = resources.getContainerResources().createEventLink(EventConstants.ACTION, context);
        Element element = null;
        if (pageIndex == currentPage) {
            element = writer.element("a", "href", zoneIsNull ? link : "#", "class", "current");
        } else {
            element = writer.element("a", "href", zoneIsNull ? link : "#");
        }
        writer.write(Long.toString(pageIndex));
        writer.end();

        if (!zoneIsNull) {
            String id = jsSupport.allocateClientId(resources);

            element.attribute("id", id);

            clientBehaviorSupport.linkZone(id, zone, link);
        }
    }

}
